package com.smart.campus.web.controller.api;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.smart.campus.common.annotation.Log;
import com.smart.campus.common.core.controller.BaseController;
import com.smart.campus.common.core.domain.AjaxResult;
import com.smart.campus.common.core.page.TableDataInfo;
import com.smart.campus.common.enums.BusinessType;
import com.smart.campus.common.utils.DateUtils;
import com.smart.campus.common.utils.poi.ExcelUtil;
import com.smart.campus.school.domain.ScPaymentBill;
import com.smart.campus.school.domain.request.PaymentBillRequest;
import com.smart.campus.school.service.IScPaymentBillService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.iherus.codegen.qrcode.SimpleQrcodeGenerator;
import org.iherus.codegen.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 缴费单Controller
 *
 * @author Zhihe.Li
 * @date 2020-05-13
 */
@Controller
@RequestMapping("/api/wxpay")
@CrossOrigin(origins = "*",maxAge = 3600)
public class ApiWxPayController extends BaseController {

    @Autowired
    private IScPaymentBillService scPaymentBillService;


    @Value("${wxpay.appId}")
    private String appId;

    @Value("${wxpay.appSecret}")
    private String appSecret;

    @Value("${wxpay.certPath}")
    private String certPath;

    @Value("${wxpay.domain}")
    private String domain;

    @Value("${wxpay.mchId}")
    private String mchId;

    @Value("${wxpay.partnerKey}")
    private String partnerKey;

    @Value("${wxpay.notifyUrl}")
    private String notifyUrl;

    @Value("${wxpay.refundNotifyUrl}")
    private String refundNotifyUrl;

    private WxPayApiConfig wxPayApiConfig;

    @PostConstruct
    public WxPayApiConfig getApiConfig() {
        wxPayApiConfig = WxPayApiConfig.builder()
                .appId(appId)
                .mchId(mchId)
                .partnerKey(partnerKey)
                .certPath(certPath)
                .domain(domain)
                .build();
        return wxPayApiConfig;
    }


    @Log(title = "获取微信小程序支付参数", businessType = BusinessType.UPDATE)
    @PostMapping("/getBillWxminiappPayParams")
    @ResponseBody
    public AjaxResult getBillWxminiappPayParams(Long id,String openId,HttpServletRequest request) {
        ScPaymentBill scPaymentBill = scPaymentBillService.selectScPaymentBillById(id);
        if(scPaymentBill.getStatus()==1){
            return AjaxResult.error("此账单已缴费，不能重复缴费");
        }

        String tradeNo = IdUtil.fastSimpleUUID();
        scPaymentBill.setPaymentNo(tradeNo);//设置微信支付流水号为账单号
        scPaymentBill.setPaymentType(1);
        scPaymentBillService.updateScPaymentBill(scPaymentBill);

        String subject = "";
        if(scPaymentBill.getPaymentCategory() == 1){
            subject = "学费";
        }else if(scPaymentBill.getPaymentCategory() == 2){
            subject= "杂费";
        }

        String body = scPaymentBill.getSchoolYear()+"第" + scPaymentBill.getTerm()+"学期学费";
        String ip = IpKit.getRealIp(request);
        if (StringUtils.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .attach(subject)
                .out_trade_no(tradeNo)
                .total_fee(new BigDecimal(scPaymentBill.getAmount()).multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString())
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, params);

        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            return AjaxResult.error(result.get("err_code_des"));
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            return AjaxResult.error(result.get("err_code_des"));
        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");
        Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(wxPayApiConfig.getAppId(), prepayId,
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
        packageParams.put("outTradeNo",tradeNo);
        String jsonStr = JSON.toJSONString(packageParams);
        System.out.println("支付结果------------------"+jsonStr);
        return AjaxResult.success("获取支付参数成功",jsonStr);
    }
    /**
     * 异步通知
     */
    @RequestMapping(value = "/notify", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String notify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
        String returnCode = params.get("return_code");

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (WxPayKit.verifyNotify(params, partnerKey, SignType.HMACSHA256)) {
            if (WxPayKit.codeIsOk(returnCode)) {
                String tradeNo = params.get("out_trade_no");
                // 更新订单信息
                ScPaymentBill scPaymentBill = scPaymentBillService.selectScPaymentBillByPaymentNo(tradeNo);
                if (scPaymentBill.getStatus() == 0) {
                    scPaymentBill.setStatus(1);
                    scPaymentBill.setPaymentTime(DateUtils.getNowDate());
                    scPaymentBill.setUpdateTime(DateUtils.getNowDate());
                    scPaymentBillService.updateScPaymentBill(scPaymentBill);
                }
            }
        }
        // 发送通知等
        Map<String, String> xml = new HashMap<String, String>(2);
        xml.put("return_code", "SUCCESS");
        xml.put("return_msg", "OK");
        return WxPayKit.toXml(xml);
    }
}
